﻿using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.Drawing;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;

namespace UCNKompetenceBors
{
    public class GeneralTools
    {

        /// <summary>
        /// Truncates the input string, based on the maxLength parameter.
        /// </summary>
        /// <param name="input">Specifies the input string that is to be truncated.</param>
        /// <param name="maxLength">Specifies the max length at which the input string should be truncated.</param>
        /// <param name="stopAt">Specificies the character at which the output string, should stop at the last index of.</param>
        /// <returns>Returns a truncated version of the input string.</returns>
        public static string TruncateString(string input, int maxLength, string stopAt)
        {
            string x = input;

            if (input.Length >= maxLength)
            {
                x = input.Substring(0, maxLength);
                int lastDotIndex = x.LastIndexOf(stopAt) + 1;
                x = x.Substring(0, lastDotIndex);
            }

            return x;
        }

        /// <summary>
        /// Generates a QueryString based on a NameValueCollection.
        /// </summary>
        /// <param name="nvc">Specifies the NameValueCollection used to generate the QueryString.</param>
        /// <returns>Returns a QueryString based on the nvc parameter.</returns>
        public static string GenerateQueryString(NameValueCollection nvc)
        {
            StringBuilder sb = new StringBuilder("?");
            bool first = true;
            foreach (string key in nvc.AllKeys)
            {
                foreach (string value in nvc.GetValues(key))
                {
                    if (!first)
                    {
                        sb.Append("&");
                    }

                    sb.AppendFormat("{0}={1}", Uri.EscapeDataString(key), Uri.EscapeDataString(value));

                    first = false;
                }
            }

            return sb.ToString();
        }

        #region Pagination
        /// <summary>
        /// Generates an URL based on the toPage, queryString and path parameters.
        /// </summary>
        /// <param name="toPage">Specifices the page number to generate a link to.</param>
        /// <param name="queryString">Specifies the QueryString to add to the generated URL.</param>
        /// <param name="path">Specifies the path to be added to the generated URL.</param>
        /// <returns>Returns an URL to a specific page.</returns>
        private static string GetLink(int toPage, string queryString, string path)
        {
            NameValueCollection query = HttpUtility.ParseQueryString(queryString);
            query["p"] = toPage.ToString();

            string url = path;

            for (int i = 0; i < query.Count; i++)
            {
                url += string.Format("{0}{1}={2}",
                    i == 0 ? "?" : "&",
                    query.Keys[i],
                    string.Join(",", query.GetValues(i)));
            }

            return url;
        }

        /// <summary>
        /// Generates a list of WebControls containing the controls necessary, to create Pagination based on the input parameters.
        /// </summary>
        /// <param name="pageLinksToShow">Specifices the amount of page links to have visible simultaneously.</param>
        /// <param name="pageCount">Specifies the total amount of pages.</param>
        /// <param name="currentPage">Specifies the current page.</param>
        /// <param name="queryString">Specifies the QueryString used when generating the NavigateUrl of each link.</param>
        /// <param name="path">Specifies the Path used when generating the NavigateUrl of each link.</param>
        /// <returns>Returns a list of WebControls.</returns>
        public static List<WebControl> CreatePagination(int pageLinksToShow, int pageCount, int currentPage, string queryString, string path)
        {
            List<WebControl> links = new List<WebControl>();

            int min = Math.Min(Math.Max(0, currentPage - (pageLinksToShow / 2)), Math.Max(0, pageCount - pageLinksToShow + 1));
            int max = Math.Min(pageCount, min + pageLinksToShow);

            int previous = currentPage - 1;
            int next = currentPage + 1;

            if (previous > 0)
            {
                HyperLink hyLinkPrev = new HyperLink();
                hyLinkPrev.Text = "<";
                hyLinkPrev.NavigateUrl = GetLink(previous, queryString, path);
                hyLinkPrev.CssClass = "link paginationNumbers";
                links.Add(hyLinkPrev);
            }

            if (min > 0)
            {
                HyperLink hyLinkFirst = new HyperLink();
                hyLinkFirst.Text = "1";
                hyLinkFirst.NavigateUrl = GetLink(1, queryString, path);
                hyLinkFirst.CssClass = "link paginationNumbers" + (currentPage == 1 ? " paginationCurrent" : string.Empty);
                links.Add(hyLinkFirst);
            }

            if (min > 0)
            {
                Label spacer = new Label();
                spacer.Text = "&hellip;";
                spacer.CssClass = "paginationSpacer";
                links.Add(spacer);
            }

            for (int i = min; i < max; i++)
            {
                HyperLink hyLink = new HyperLink();
                hyLink.Text = (i + 1).ToString();
                hyLink.NavigateUrl = GetLink(i + 1, queryString, path);
                hyLink.CssClass = "link paginationNumbers" + (currentPage == i + 1 ? " paginationCurrent" : string.Empty);
                links.Add(hyLink);
            }

            if (max < pageCount)
            {
                Label spacer = new Label();
                spacer.Text = "&hellip;";
                spacer.CssClass = "paginationSpacer";
                links.Add(spacer);
            }

            if (max < pageCount)
            {
                HyperLink hyLinkLast = new HyperLink();
                hyLinkLast.Text = pageCount.ToString();
                hyLinkLast.NavigateUrl = GetLink(pageCount, queryString, path);
                hyLinkLast.CssClass = "link paginationNumbers" + (currentPage == pageCount ? " paginationCurrent" : string.Empty);
                links.Add(hyLinkLast);
            }

            if (next <= pageCount)
            {
                HyperLink hyLinkNext = new HyperLink();
                hyLinkNext.Text = ">";
                hyLinkNext.NavigateUrl = GetLink(currentPage + 1, queryString, path);
                hyLinkNext.CssClass = "link paginationNumbers";
                links.Add(hyLinkNext);
            }

            return links;
        }
        #endregion

        #region Globalization

        /// <summary>
        /// Sets the CurrentUICulture and the CurrentCulture.
        /// </summary>
        /// <param name="culture">Specifies the culture to use when setting the CurrentUICulture and the CurrentCulture.</param>
        public static void SetCulture(string culture)
        {
            Thread.CurrentThread.CurrentUICulture = new CultureInfo(culture);
            Thread.CurrentThread.CurrentCulture = new CultureInfo(culture);

            HttpContext.Current.Session["MyUICulture"] = Thread.CurrentThread.CurrentUICulture;
            HttpContext.Current.Session["MyCulture"] = Thread.CurrentThread.CurrentCulture;
        }
        #endregion

        #region Image
        
        /// <summary>
        /// Resizes an image with a fixed width, based on the input parameters. 
        /// </summary>
        /// <param name="maxWidth">Specifies the max width of the image.</param>
        /// <param name="image">Specifies the image to be resized.</param>
        /// <param name="filePath">Specifies the path of the image.</param>
        public static void ResizeImage(int maxWidth, System.Drawing.Image image, string filePath)
        {
            int newWidth, newHeight;
            double ratio = (double)maxWidth / (double)image.Width;

            newWidth = maxWidth;
            newHeight = (int)Math.Round(image.Height * ratio);
            
            Bitmap bitmap = new Bitmap(newWidth, newHeight);

            Graphics imageGraph = Graphics.FromImage(bitmap);
            imageGraph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            imageGraph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            imageGraph.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            Rectangle imageRectangle = new Rectangle(0, 0, newWidth, newHeight);
            imageGraph.DrawImage(image, imageRectangle);

            bitmap.Save(filePath, image.RawFormat);

            imageGraph.Dispose();
            bitmap.Dispose();
        }

        /// <summary>
        /// Resizes an image to a thumbnail, with a fixed height, based on the input parameters. 
        /// </summary>
        /// <param name="maxHeight">Specifies the max height of the thumbnail.</param>
        /// <param name="image">Specifies the image to be resized.</param>
        /// <param name="filePath">Specifies the path of the image.</param>
        public static void CreateThumbnail(int maxHeight, System.Drawing.Image image, string filePath)
        {
            int newWidth, newHeight;
            double ratio = (double)maxHeight / (double)image.Height;

            newWidth = (int)Math.Round(image.Width * ratio);;
            newHeight = maxHeight;

            Bitmap bitmap = new Bitmap(newWidth, newHeight);

            Graphics imageGraph = Graphics.FromImage(bitmap);
            imageGraph.CompositingQuality = System.Drawing.Drawing2D.CompositingQuality.HighQuality;
            imageGraph.SmoothingMode = System.Drawing.Drawing2D.SmoothingMode.HighQuality;
            imageGraph.InterpolationMode = System.Drawing.Drawing2D.InterpolationMode.HighQualityBicubic;

            Rectangle imageRectangle = new Rectangle(0, 0, newWidth, newHeight);
            imageGraph.DrawImage(image, imageRectangle);

            bitmap.Save(filePath, image.RawFormat);

            imageGraph.Dispose();
            bitmap.Dispose();
            image.Dispose();
        }
        #endregion
    }
}